#include "device/ec200/AtNetworkMqttOnenetEC200.h"

#define WRITE_INTERVAL 1000 // 并发控制

#define CONNECT_CFG1 "AT+QMTCFG=\"version\",%d,4\r\n"            // MQTT配置-指令1
#define CONNECT_CFG2 "AT+QMTCFG=\"recv/mode\",%d,0,1\r\n"        // MQTT配置-指令2
#define CONNECT_CFG3 "AT+QMTCFG=\"keepalive\",%d,120\r\n"        // MQTT配置-指令3
#define CONNECT_CFG4 "AT+QMTCFG=\"onenet\",%d,\"%s\",\"%s\"\r\n" // MQTT配置-指令4

#define CONNECT_CMD1 "AT+QMTOPEN=%d,\"%s\",%d\r\n" // 打开MQTT连接
#define CONNECT_CMD2 "AT+QMTCONN=%d,\"%s\"\r\n"    // 注册MQTT连接

bool AtNetworkMqttOnenetEC200::connect(uint32_t timeout) {
  // MQTT 通道配置-----------------------------------------------------------------
  this->device->streamPrintfClear(CONNECT_CFG1, this->cid);
  this->device->streamPrintfClear(CONNECT_CFG2, this->cid);
  this->device->streamPrintfClear(CONNECT_CFG3, this->cid);

  // 设置ONENET产品ID&产品密钥-----------------------------------------------------
  this->device->streamPrintfClear(CONNECT_CFG4, this->cid, this->username, this->password);

  // 打开MQTT连接(+QMTOPEN: <client_idx>,<result>)--------------------------------
  this->device->streamPrintfClear(CONNECT_CMD1, this->cid, this->host, this->port);
  if (this->device->wait(30000, "+QMTOPEN: ") != AT_RCODE1) {
    return false;
  }
  if (this->device->streamGetInt(1, ',') != this->cid) {
    return false;
  }
  if (this->device->streamGetInt(1) != 0) {
    return false;
  }

  // 初始化MQTT连接(+QMTCONN: <client_idx>,<state>)------------------------------
  this->device->streamPrintfClear(CONNECT_CMD2, this->cid, this->clientId);
  if (this->device->wait(30000, "+QMTCONN: ") != AT_RCODE1) {
    return false;
  }
  if (this->device->streamGetInt(1) != this->cid) {
    return false;
  }

  // 初始化MQTT所需的URC配置----------------------------------------------------
  this->device->add_urc_callback(this->route);
  this->device->add_urc_callback(this->state);

  // 等待MQTT连接成功----------------------------------------------------------
  uint32_t expire_time = millis() + timeout * 10;
  while (timeout > 0 && expire_time > millis()) {
    if (this->isConnected(timeout)) {
      return true;
    }

    delay(500);
  }

  return false;
}

bool AtNetworkMqttOnenetEC200::publish(const char *topic, char *body, size_t length) {
  while ((this->lastWriteTime + WRITE_INTERVAL) > millis()) {
    delay(50);
  }

  if (AtNetworkMqttClient::publish(topic, body, length)) {
    this->lastWriteTime = millis();

    return true;
  }

  return false;
}

bool AtNetworkMqttOnenetEC200::subscribe(AtNetworkMqttTopic *topic, uint8_t qos) {
  while ((this->lastWriteTime + WRITE_INTERVAL) > millis()) {
    delay(50);
  }

  if (AtNetworkMqttClient::subscribe(topic, qos)) {
    this->lastWriteTime = millis();

    return true;
  }

  return false;
}

bool AtNetworkMqttOnenetEC200::unsubscribe(AtNetworkMqttTopic *topic) {
  while ((this->lastWriteTime + WRITE_INTERVAL) > millis()) {
    delay(50);
  }

  if (AtNetworkMqttClient::unsubscribe(topic)) {
    this->lastWriteTime = millis();

    return true;
  }

  return false;
}